package com.baixun.gassystem.service.impl;

import com.baixun.gascommon.config.ApiConfig;
import com.baixun.gascommon.utils.HttpClientUtil;
import com.baixun.gascommon.utils.R;
import com.baixun.gascommon.utils.RedisUtils;
import com.baixun.gasentity.dto.VideoDto;
import com.baixun.gasentity.entity.SysDepartment;
import com.baixun.gasentity.entity.SysVideoMessage;
import com.baixun.gassystem.mapper.SysDepartmentMapper;
import com.baixun.gassystem.mapper.SysVideoMessageMapper;
import com.baixun.gassystem.service.SysVideoMessageService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.fasterxml.jackson.core.type.TypeReference;


import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
* @author 智少
* @description 针对表【sys_video_message】的数据库操作Service实现
* @createDate 2024-09-29 15:43:31
*/
@Service
public class SysVideoMessageServiceImpl extends ServiceImpl<SysVideoMessageMapper, SysVideoMessage>
    implements SysVideoMessageService {


    @Autowired
    private SysVideoMessageMapper sysVideoMessageMapper;

    @Autowired
    private RedisUtils redisUtils;

    @Autowired
    private SysDepartmentMapper sysDepartmentMapper;

    /**
     * 树形结构[到最后一个子节点]
     *
     * @param videoDto
     * @return
     */
    @Override
    public R<List<SysVideoMessage>> getList(VideoDto videoDto) {
        // 创建查询条件
        QueryWrapper<SysVideoMessage> queryWrapper = new QueryWrapper<>();

        // 检查 videoDto 是否为空
        if (videoDto != null) {
            // 如果 poineId 不为空，则根据 poineId 过滤
            if (videoDto.getPoineId() != null) {
                queryWrapper.eq("poine_id", videoDto.getPoineId());
            }
            // 如果 pointName 不为空，则根据 pointName 模糊查询
            if (videoDto.getPointName() != null) {
                queryWrapper.like("point_name", videoDto.getPointName());
            }
        }

        // 执行查询
        List<SysVideoMessage> videoMessages = sysVideoMessageMapper.tree();

        // 构建树形结构
        List<SysVideoMessage> tree = buildTree(videoMessages);
        System.out.println(tree);

        // 返回查询结果
        return R.success(tree);
    }

    /**
     * 实时监控树形架构
     */
    @Override
    public List<SysVideoMessage> getTree(Long userId) throws Exception {

        //使用用户的token去访问树形结构接口，把获取数据返回前端，然后把去点位表里面获取坐标假如树形结构返回给前端
        // Step 1: 从 Redis 获取用户 token
        String tokenKey = "token:" + userId;
        String token = redisUtils.get(tokenKey);
        if (token == null || token.isEmpty()) {
            throw new Exception("No valid token found in Redis.");
        }

        // Step 2: 构建请求 URL
        StringBuilder treeSearchUrl = new StringBuilder(ApiConfig.DOMAIN + ApiConfig.TREE_SEARCH_API);
        System.out.println("Constructed URL: " + treeSearchUrl);

        // Step 3: 设置请求头
        HashMap<String, String> headers = new HashMap<>();
        headers.put("Cookie", "SAAS_SESSION=" + token);
        headers.put("Content-Type", "application/json; charset=UTF-8");

        // Step 4: 发送 GET 请求
        String response = HttpClientUtil.sendGetRequest(treeSearchUrl.toString(), headers);

        // Step 5: 校验响应结果
        if (response == null || response.isEmpty()) {
            throw new Exception("Failed to fetch tree data from API.");
        }

        // Step 6: 解析响应为 SysVideoMessage 列表
        ObjectMapper objectMapper = new ObjectMapper();
        List<SysVideoMessage> nodes;
        try {
            nodes = objectMapper.readValue(response, new TypeReference<List<SysVideoMessage>>() {
            });
        } catch (Exception e) {
            throw new Exception("Failed to parse API response into SysVideoMessage list.", e);
        }

        // Step 7: 构建树形结构
        return buildTree(nodes);
    }

    /**
     * 监控树形架构
     */
    @Override
    public List<SysVideoMessage> getTreeArea(Long userId) throws Exception {
        // Step 1: 从 Redis 获取用户 token
        String tokenKey = "token:" + userId;
        String token = redisUtils.get(tokenKey);
        if (token == null || token.isEmpty()) {
            throw new Exception("No valid token found in Redis.");
        }

// Step 2: 构建请求 URL
        StringBuilder treeSearchUrl = new StringBuilder(ApiConfig.DOMAIN + ApiConfig.TREE_SEARCH_API);
        System.out.println("Constructed URL: " + treeSearchUrl);

// Step 3: 设置请求头
        HashMap<String, String> headers = new HashMap<>();
        headers.put("Cookie", "SAAS_SESSION=" + token);
        headers.put("Content-Type", "application/json; charset=UTF-8");

// Step 4: 发送 GET 请求
        String response = HttpClientUtil.sendGetRequest(treeSearchUrl.toString(), headers);

// Step 5: 校验响应结果
        if (response == null || response.isEmpty()) {
            throw new Exception("Failed to fetch tree data from API.");
        }

// Step 6: 解析响应数据
        ObjectMapper objectMapper = new ObjectMapper();
        JsonNode rootNode;
        try {
            rootNode = objectMapper.readTree(response);
        } catch (Exception e) {
            throw new Exception("Failed to parse API response into JSON.", e);
        }

// Step 7: 提取 type 为 "AREA" 的节点
        List<SysVideoMessage> areaNodes = new ArrayList<>();
        if (rootNode.has("data")) {
            JsonNode dataNodes = rootNode.get("data");
            for (JsonNode node : dataNodes) {
                if ("AREA".equals(node.get("type").asText())) {
                    SysVideoMessage videoMessage = new SysVideoMessage();
                    videoMessage.setId(node.get("id").asLong());
                    videoMessage.setParentId(node.get("parentId").asLong());
                    videoMessage.setType(node.get("type").asText());
                    videoMessage.setPointCount(node.get("pointCount").asInt());
                    videoMessage.setOnlinePointCount(node.get("onlinePointCount").asInt());
                    areaNodes.add(videoMessage);
                }
                if (node.has("children")) {
                    extractAreaChildren(node.get("children"), areaNodes);
                }
            }
        }

// Step 8: 调用现有的 buildTree 方法
        List<SysVideoMessage> treeStructure = buildTree(areaNodes);

// Step 9: 转发给前端
        return treeStructure;
    }

    /**
     * 递归提取子节点中 type 为 "AREA" 的节点
     */
    private void extractAreaChildren(JsonNode nodes, List<SysVideoMessage> areaNodes) {
        if (nodes == null || !nodes.isArray()) {
            return;
        }
        for (JsonNode node : nodes) {
            if ("AREA".equals(node.get("type").asText())) {
                SysVideoMessage videoMessage = new SysVideoMessage();
                videoMessage.setId(node.get("id").asLong());
                videoMessage.setParentId(node.get("parentId").asLong());
                videoMessage.setType(node.get("type").asText());
                videoMessage.setPointCount(node.get("pointCount").asInt());
                videoMessage.setOnlinePointCount(node.get("onlinePointCount").asInt());
                areaNodes.add(videoMessage);
            }
            if (node.has("children")) {
                extractAreaChildren(node.get("children"), areaNodes);
            }
        }
    }


    /**
     * 构建树形结构
     */
    private List<SysVideoMessage> buildTree(List<SysVideoMessage> nodes){
        //将map节点按id映射，方便快速查找
        Map<Long,SysVideoMessage> nodeMap = nodes.stream()
                .collect(Collectors.toMap(SysVideoMessage::getId, node -> node));

        //存储根节点
        List<SysVideoMessage> rootNodes =new ArrayList<>();

        //构建父子关系
        for (SysVideoMessage node : nodes) {
            Long parentId = node.getParentId();
            if (parentId == null || parentId == 0){
                // 没有父节点或父节点为 0 的节点为根节点
                rootNodes.add(node);
            }else {
                // 找到父节点并添加当前节点为子节点
                SysVideoMessage parent = nodeMap.get(parentId);
                if (parent != null){
                    parent.getSysVideoMessageList().add(node);
                }
            }
        }
        return rootNodes;
    }






}




